﻿/*
****************************************************************************************************************
*= = 版权信息：Copyright (C) 356 - 999. Ombres Industry Empiral. All rights reserved.
*= = 文件名称：Windurb.cxx
*= = 功能描述：风之谷服务器定义主文件
*= = 编写人员：Carlyon W. Tung
****************************************************************************************************************
*/

/*
*===============================================================================================================
*= = 声明文件
*===============================================================================================================
*/

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <memory>
#include <string>
#include <type_traits>
#include <utility>

#include <boost/array.hpp>
#include <boost/asio.hpp>

#include <boost/config.hpp>
#include <boost/format.hpp>
#include <boost/thread.hpp>
#include <boost/version.hpp>

#include <log4cxx/helpers/exception.h>
#include <log4cxx/logger.h>
#include <log4cxx/propertyconfigurator.h>

#include "Windurb.h"

/*
*===============================================================================================================
*= = 预处理声明
*===============================================================================================================
*/

#ifdef HAVE_CONFIG_H
    #include <config.h>
#endif // End of HAVE_CONFIG_H

/*
*===============================================================================================================
*= = 宏定义
*===============================================================================================================
*/

#define COPYRIGHT "Copyright (C) 356 - 999. Ombres Industry Empiral. All rights reserved."
#define WUVERSION "Windurb 1.0.1 - 365"
#define WUAUTHORS "Carlyon W. Tung    loongs@syuusui.com"

/*
*===============================================================================================================
*= = 命名空间
*===============================================================================================================
*/

using namespace boost;
using namespace boost::asio;
using namespace boost::asio::ip;
using namespace log4cxx;
using namespace log4cxx::helpers;
using namespace std;

/*
*===============================================================================================================
*= = 全局变量
*===============================================================================================================
*/

#ifdef __INSIGHT_OS_WINDOWS__
static const string WindurbLogProperties = ".\\Asgard\\Windurb.properties";
#else
static const string WindurbLogProperties = "/etc/Windurb/Windurb.properties";
#endif

static uint32_t g_hardware_concurrency = 1;
LoggerPtr g_rootLogger = nullptr;

/*
*===============================================================================================================
*= = 类定义
*===============================================================================================================
*/

class handler_memory : public OObject
{
public:
    handler_memory()
        : m_in_use(false)
    {
        //
    }

    handler_memory(const handler_memory&) = delete;
    handler_memory& operator=(const handler_memory&) = delete;

    void* allocate(std::size_t size)
    {
        if (!m_in_use && size < sizeof(m_storage))
        {
            m_in_use = true;
            return &m_storage;
        }
        else
        {
            return ::operator new(size);
        }
    }

    void deallocate(void* pointer)
    {
        if (pointer == &m_storage)
        {
            m_in_use = false;
        }
        else
        {
            ::operator delete(pointer);
        }
    }

private:
    typename std::aligned_storage<1024>::type m_storage{};

    bool m_in_use;
};

template <typename T>
class handler_allocator : public OObject
{
public:
    using value_type = T;

    explicit handler_allocator(handler_memory& mem)
        : m_handler_memory(mem)
    {
        //
    }

    template <typename U>
    handler_allocator(const handler_allocator<U>& other) noexcept
        : m_handler_memory(other.m_handler_memory)
    {
        //
    }

    bool operator==(const handler_allocator& other) const noexcept
    {
        return &m_handler_memory == &other.m_handler_memory;
    }

    bool operator!=(const handler_allocator& other) const noexcept
    {
        return &m_handler_memory != &other.m_handler_memory;
    }

    T* allocate(std::size_t n) const
    {
        return static_cast<T*>(m_handler_memory.allocate(sizeof(T) * n));
    }

    void deallocate(T* p, std::size_t /*n*/) const
    {
        return m_handler_memory.deallocate(p);
    }

private:
    template <typename> friend class handler_allocator;

    handler_memory& m_handler_memory;
};

class session : public std::enable_shared_from_this<session>, OObject
{
public:
    session(asio::ip::tcp::socket socket)
        : m_socket(std::move(socket))
    {
        std::memset(m_data.data(), 0, m_data.size() * sizeof(char));
    }

    void start()
    {
        LOG4CXX_TRACE(g_rootLogger, boost::format("Windurb - Windurb: Remote client IP is: %1%.") % m_socket.remote_endpoint().address());

        do_read();
    }

private:
    void do_read()
    {
        auto self(shared_from_this());
        m_socket.async_read_some(boost::asio::buffer(m_data),
            boost::asio::bind_allocator(
                handler_allocator<int>(m_handler_memory),
                [this, self](boost::system::error_code ec, std::size_t length)
                {
                    if (!ec)
                    {
                        do_write(length);
                    }
                }));
    }

    void do_write(std::size_t length)
    {
        auto self(shared_from_this());
        boost::asio::async_write(m_socket, boost::asio::buffer(m_data, length),
            boost::asio::bind_allocator(
                handler_allocator<int>(m_handler_memory),
                [this, self](boost::system::error_code ec, std::size_t /* length */)
                {
                    if (!ec)
                    {
                        do_read();
                    }
                }));
    }

private:
    asio::ip::tcp::socket m_socket;

    std::array<char, 1024> m_data;

    handler_memory m_handler_memory;
};

class windurb_server : public OObject
{
public:
    windurb_server(boost::asio::io_context& io_context, short port)
        : m_acceptor(io_context, asio::ip::tcp::endpoint(asio::ip::tcp::v4(), port))
    {
        do_accept();
    }

private:
    void do_accept()
    {
        m_acceptor.async_accept(
            [this](boost::system::error_code ec, asio::ip::tcp::socket socket)
            {
                if (!ec)
                {
                    std::make_shared<session>(std::move(socket))->start();
                }

                do_accept();
            });
    }

private:
    asio::ip::tcp::acceptor m_acceptor;
};

/*
*===============================================================================================================
*= = 函数定义
*===============================================================================================================
*/

/*
*===============================================================================================================
*= = 函数名称：main
*= = 功能描述：基本入口函数
*= = 入口参数：int、char **
*= = 出口参数：int
*===============================================================================================================
*/

int main(int argc, char *argv[])
{
    std::cout << COPYRIGHT << std::endl;
    std::cout << WUVERSION << std::endl;
    std::cout << WUAUTHORS << std::endl;

    try
    {
        PropertyConfigurator::configure(WindurbLogProperties);
    }
    catch (...)
    {
        std::cout << "Windurb - Windurb: log4cxx initial ERROR!" << std::endl;

        return -1;
    }

    g_rootLogger = Logger::getRootLogger();

    LOG4CXX_INFO(g_rootLogger, "Windurb - Windurb: Initial SUCCESS.");
    LOG4CXX_DEBUG(g_rootLogger, boost::format("Boost version is %1%.") % BOOST_LIB_VERSION);

    try
    {
        g_hardware_concurrency = boost::thread::hardware_concurrency();
        LOG4CXX_DEBUG(g_rootLogger, boost::format("Windurb - Windurb: Hardware concurrency is %1%.") % g_hardware_concurrency);

        boost::asio::io_context windurb_io_context;
        windurb_server ws(windurb_io_context, std::atoi("32404"));
        windurb_io_context.run();
    }
    catch (std::exception& e)
    {
        LOG4CXX_ERROR(g_rootLogger, boost::format("Windurb - Windurb: Exception: %1%.") % e.what());
    }

    return 0;
}


/*
****************************************************************************************************************
*= = 文件结束
****************************************************************************************************************
*/


